package com.example.springdemo.handlers;

import com.example.springdemo.annotation.RestResponse;
import com.example.springdemo.domain.base.BaseRes;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * ResHandler
 * 统一返回格式处理器
 *
 * @author wenguang
 * @date 2021/11/11 17:04
 */
@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ResHandler implements ResponseBodyAdvice<Object> {

    public static final String RESPONSE_RESULT_KEY = "RESPONSE-RESULT-KEY";

    private final ObjectMapper objectMapper;

    private final HttpServletRequest servletRequest;

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        RestResponse attribute = (RestResponse) servletRequest.getAttribute(RESPONSE_RESULT_KEY);
        return Objects.nonNull(attribute);
    }

    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<?
        extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {
        if (o instanceof String) {
            return objectMapper.writeValueAsString(BaseRes.success(o));
        }

        if (o instanceof BaseRes) {
            return o;
        }

        return BaseRes.success(o);
    }

}
